package com.ld.shieldsb.common.core.validate;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

/**
 * 验证专用工具类
 *
 * @ClassName: ValidateService
 * @author: 张和祥
 * @date: 2018年2月3日 下午8:59:56
 */
public class ValidateUtil {

    /**
     * 验证姓名是否符合规则
     *
     * @Title: checkCreditCode
     * @author 张和祥
     * @date 2018年2月3日 下午9:01:32
     * @param name
     */
    public static boolean checkName(String name) {
        if (StringUtils.isBlank(name) || name.contains("某某")) {
            return false;
        }
        // 必须是汉字。姓名中可以包含·（少数民族？）；企业名称可以包含（）或()。
        Pattern pattern = Pattern.compile("^([\\u4e00-\\u9fa5\\·\\(\\)\\（\\）]{1,200}|[a-zA-Z\\.\\(\\)\\s]{1,200})$");
        return pattern.matcher(name).matches();
    }

    /**
     * 验证统一社会信用代码是否符合规则
     *
     * @Title: checkCreditCode
     * @author 张和祥
     * @date 2018年2月3日 下午9:01:32
     * @param creditCode
     */
    public static boolean checkCreditCode(String creditCode) {
        /*
         * 验证规则： 1、由阿拉伯数字或大写英文字母（不使用I、O、Z、S、V）组成。 2、第1位为登记管理部门代码，只能是：1 5 9 Y 3、第2位：机构类别代码（共一位字符） 4、第3位~第8位为登记管理机关行政区划码，必须是六位阿拉伯数字
         * 5、第9位~第17位：主体标识码（组织机构代码）（共九位字符） 6、第18位：校验码​（共一位字符）
         */
        if (isEmpty(creditCode) || creditCode.length() != 18) {
            return false;
        }

        Pattern pattern = Pattern.compile("^[0-9a-hj-npqrtuwxyA-HJ-NPQRTUWXY]{2}\\d{6}[0-9a-zA-Z]{10}$");
        if (pattern.matcher(creditCode).matches()) {
            return checkCreditCode2Char(creditCode) && creditCodeCheckFormula(creditCode);
        }
        return false;
    }

    /**
     * 统一社会信用代码前2位判断，参考https://wenku.baidu.com/view/0b6dfd98162ded630b1c59eef8c75fbfc67d944f.html
     *
     * @Title: checkCreditCode2Char
     * @author 张和祥
     * @date 2018年2月7日 下午3:43:54
     */
    private static boolean checkCreditCode2Char(String creditCode) {
        String[] strS = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "N", "Y" };
        List<String> strList = Arrays.asList(strS);
        // 第1位为登记管理部门代码1机构编制2外交3教育4公安5民政6司法7交通运输8文化9工商A旅游局B宗教事务管理C全国总工会D人民解放军总后勤部E省级人民政府F地市级人民政府G区县级人民政府Y其他
        String firstWord = creditCode.substring(0, 1);
        // 第2位：机构类别代码
        String secondWord = creditCode.substring(1, 2);
        if (strList.contains(firstWord)) {
            if ("1".equals(firstWord) || "N".equals(firstWord)) {
                return "1".equals(secondWord) || "2".equals(secondWord) || "3".equals(secondWord) || "9".equals(secondWord);
            } else if ("5".equals(firstWord)) {
                return "1".equals(secondWord) || "2".equals(secondWord) || "3".equals(secondWord) || "4".equals(secondWord)
                        || "9".equals(secondWord);
            } else if ("2".equals(firstWord) || "4".equals(firstWord) || "8".equals(firstWord) || "A".equals(firstWord)) {
                return "1".equals(secondWord) || "9".equals(secondWord);
            } else if ("3".equals(firstWord)) {
                return "1".equals(secondWord) || "2".equals(secondWord) || "3".equals(secondWord) || "4".equals(secondWord)
                        || "5".equals(secondWord) || "9".equals(secondWord);
            } else if ("6".equals(firstWord) || "7".equals(firstWord)) {
                return "1".equals(secondWord) || "2".equals(secondWord) || "9".equals(secondWord);
            } else if ("9".equals(firstWord)) {
                return "1".equals(secondWord) || "2".equals(secondWord) || "3".equals(secondWord);
            } else if ("Y".equals(firstWord)) {
                return "1".equals(secondWord);
            }
        }
        return false;
    }

    /**
     * 统一社会信用代码校验算法。参考：GB 32100-2015 法人和其他组织统一社会信用代码编码规则
     *
     * @author 张和祥
     * @date 2019年3月26日 下午17:00:00
     * @param creditCode
     * @return
     */
    private static boolean creditCodeCheckFormula(String creditCode) {
        String baseCode = "0123456789ABCDEFGHJKLMNPQRTUWXY";
        char[] baseCodeArray = baseCode.toCharArray();
        HashMap<Character, Integer> codes = new HashMap<>();
        for (int i = 0; i < baseCode.length(); i++) {
            codes.put(baseCodeArray[i], i);
        }
        char[] businessCodeArray = creditCode.toCharArray();
        Character check = businessCodeArray[17];
        if (baseCode.indexOf(check) == -1) {
            return false;
        }
        int[] wi = { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28 };
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            Character key = businessCodeArray[i];
            if (baseCode.indexOf(key) == -1) {
                return false;
            }
            sum += (codes.get(key) * wi[i]);
        }
        int value = 31 - sum % 31;
        if (value == 31) { // 根据规范，如果取余函数为0，则返回0，因为最大就是30。
            value = 0;
        }
        return value == codes.get(check);
    }

    /**
     * 验证组织机构代码
     *
     * @Title: checkOrganCode
     * @author 张和祥
     * @date 2018年2月3日 下午9:46:49
     */
    public static boolean checkOrganCode(String organCode) {
        if (isEmpty(organCode) || ((organCode.length() != 9 && organCode.length() != 10))) {
            return false;
        }

        if (organCode.length() == 10 && organCode.indexOf("-") != 8) {
            return false;
        }
        organCode = organCode.replace("-", ""); // 去掉-号，便于验证
        Pattern pattern = Pattern.compile("^([0-9a-zA-Z]{8})([0-9X])$");
        // 格式校验
        if (pattern.matcher(organCode).matches()) {
            return true;
        }

//        String checkCode = "";
//        int[] in = { 3, 7, 9, 10, 5, 8, 4, 2 };
//        int a = 0;
//        for (int i = 0; i < in.length; i++) {
//            if (organCode.substring(i, i + 1).matches("[A-Z]")) {
//                a += in[i] * getAsc(organCode.substring(i, i + 1));
//            } else {
//                a += in[i] * Integer.parseInt(organCode.substring(i, i + 1));
//            }
//        }
//        int c9 = 11 - a % 11;
//        if (c9 == 10) {
//            checkCode = "X";
//        } else if (c9 == 11) {
//            checkCode = "0";
//        } else {
//            checkCode = c9 + "";
//        }
//        if (checkCode.equals(organCode.substring(9, 10))) {
//            return true;
//        }

        return false;
    }

    /**
     * 工商注册号验证
     *
     * @Title: checkIcpNo
     * @author 张和祥
     * @date 2018年2月3日 下午9:50:27
     */
    public static boolean checkIcpNo(String icpNo) {
        if (isEmpty(icpNo) || icpNo.length() != 15 && icpNo.length() != 13) {
            return false;
        }

        Pattern pattern = Pattern.compile("^[0-9]{15}|^[0-9]{13}$");
        if (pattern.matcher(icpNo).matches()) {
            return true;
        }

//        String businesslicensePrex14 = icpNo.substring(0, 14);// 获取营业执照注册号前14位数字用来计算校验码
//        String businesslicense15 = icpNo.substring(14);// 获取营业执照号的校验码
//        char[] chars = businesslicensePrex14.toCharArray();
//        int[] ints = new int[chars.length];
//        for (int i = 0; i < chars.length; i++) {
//            ints[i] = Integer.parseInt(String.valueOf(chars[i]));
//        }
//        if (businesslicense15.equals(getCheckCode(ints) + "")) {// 比较 填写的营业执照注册号的校验码和计算的校验码是否一致
//            return true;
//        }

        return false;
    }

    /**
     * 税务登记号验证
     *
     * @Title: checkIcpNo
     * @author 张和祥
     * @date 2018年2月3日 下午9:50:27
     */
    public static boolean checkTaxNo(String taxNo) {
        // 2018.02.22 税务登记号是15位或18位
        if (isEmpty(taxNo) || (taxNo.length() != 15 && taxNo.length() != 18 && taxNo.length() != 20)) {
            return false;
        }
        if (taxNo.length() == 15) {// 如果是15位，则税务登记证号由六位行政区划代码加九位组织机构代码组成
            String regionDm = taxNo.substring(0, 6);
            String organCode = taxNo.substring(6);
            Pattern pattern = Pattern.compile("^[0-9]*$");
            if (pattern.matcher(regionDm).matches() && checkOrganCode(organCode)) {
                return true;
            }
        } else { // 如果是18位或者是20位，则指判断是数字或字母
            Pattern pattern = Pattern.compile("^[0-9a-zA-Z]{18}$|^[0-9a-zA-Z]{20}");
            if (pattern.matcher(taxNo).matches()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 身份证号验证
     *
     * @Title: checkIdCard
     * @author 张和祥
     * @date 2018年2月3日 下午10:02:23
     */
    public static boolean checkIdCard(String idCard) {
        return IDCardChecker.validate(idCard).getSuccess();
    }

    /**
     * 护照验证
     */
    public static boolean checkPassport(String passport) {
        passport = passport.replaceAll("^[0-9]{9}|[A-Z][0-9]{8}|P[0-9]{7}|S[0-9]{7,8}|D[0-9]+$", "");

        return "".equals(passport);
    }

    /**
     *
     * 根据证件类型，验证证件号码
     *
     * @Title checkZjlx
     * @author 蒋承臻
     * @date 2019年3月27日 上午11:46:23
     * @return boolean
     */
    public static boolean checkZjlx(String zjlx, String zjhm) {
        if (StringUtils.isBlank(zjlx) || StringUtils.isBlank(zjhm)) {
            return false;
        }
        if (zjlx.equals("身份证")) {
            return checkIdCard(zjhm);
        } else if (zjlx.equals("护照号")) {
            return checkPassport(zjhm);
        } else if (zjlx.equals("港澳居民来往内地通行证")) {
            return isHKCard(zjhm);
        } else if (zjlx.equals("台湾居民来往大陆通行证")) {
            return isTWCard(zjhm);
        } else {// 外国人永久居留身份证
            return isWaiGuoRen(zjhm);
        }
    }

    public static boolean isHKCard(String card) {
        // 港澳居民来往内地通行证
        // 规则： H/M + 10位或6位数字
        // 样本： H1234567890
        String reg = "^([A-Z]\\d{6,10}(\\w1)?)$";
        return card.matches(reg);
    }

    public static boolean isTWCard(String card) {
        // 台湾居民来往大陆通行证
        // 规则： 新版8位或18位数字， 旧版10位数字 + 英文字母
        // 样本： 12345678 或 1234567890B
        String reg = "^\\d{8}|^[a-zA-Z0-9]{10}|^\\d{18}$";
        return card.matches(reg);
    }

    public static boolean isWaiGuoRen(String card) {
        // 外国人永久居留证
        String reg = "^[a-zA-Z]{3}\\d{12}$";
        return card.matches(reg);
    }

    /**
     * 
     * TODO(手机号验证)
     * 
     * @Title PhoneValidate
     * @author 刘金浩
     * @date 2019年7月29日 下午1:53:03
     * @param phoneStr
     * @return boolean
     */
    public static boolean PhoneValidate(String phoneStr) {

        if (StringUtils.isEmpty(phoneStr)) {
            return false;
        }
        if (phoneStr.length() != 11) {
            return false;
        }

        String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9])|(16[6]))\\d{8}$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(phoneStr);
        boolean isMatch = m.matches();
        if (!isMatch) {
            return false;
        } else {
            return true;
        }

    }

//    private static int getAsc(String st) {
//        byte[] gc = st.getBytes();
//        int ascNum = (int) gc[0] - 55;
//        return ascNum;
//    }
///^[a-zA-Z]{3}\d{12}$/

    /**
     * 获取 营业执照注册号的校验码
     *
     * @param ints
     * @return
     */
//    private static int getCheckCode(int[] ints) {
//        if (null != ints && ints.length > 1) {
//            int ti = 0;
//            int si = 0;
//            int cj = 0;
//            int pj = 10;
//            for (int i = 0; i < ints.length; i++) {
//                ti = ints[i];
//                pj = (cj % 11) == 0 ? 10 : (cj % 11);
//                si = pj + ti;
//                cj = (0 == si % 10 ? 10 : si % 10) * 2;
//                if (i == ints.length - 1) {
//                    pj = (cj % 11) == 0 ? 10 : (cj % 11);
//                    return pj == 1 ? 1 : 11 - pj;
//                }
//            }
//        }
//        return -1;
//
//    }

    /**
     * 判断字符串是否为空
     *
     * @Title: isEmpty
     * @author 张和祥
     * @date 2018年2月3日 下午9:03:33
     */
    private static boolean isEmpty(String str) {
        return str == null || "".equals(str.trim());
    }

    public static void main(String[] args) {
        System.out.println(checkCreditCode("91370611MA3PAB6M80"));
        System.out.println(checkName("易企营（烟台）网络科技有限公司"));
    }
}
